package com.tabnet.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import com.tabnet.beans.produit.Accessoire;
import com.tabnet.beans.produit.Categorie;
import com.tabnet.beans.produit.Option;
import com.tabnet.beans.produit.Produit;
import com.tabnet.dao.DAOAccessoire;
import com.tabnet.dao.DAOException;
import com.tabnet.dao.DAOFactory;
import com.tabnet.dao.DAOOption;
import com.tabnet.dao.DAOProduit;
import com.tabnet.dao.DAOUtilitaire;

public class ProduitDAOImpl implements DAOProduit {
	
	private static final String SQL_SELECT_BY_ID  		= "SELECT * FROM Produit WHERE Ref_PRD = ?";
	private static final String SQL_SELECT_LAST  		= "SELECT Ref_PRD FROM Produit ORDER BY Ref_PRD DESC LIMIT 0 , 1";
	private static final String SQL_SELECT_DISPO  		= "SELECT * FROM Produit WHERE Ref_PRD = ? AND QteStockP > 0";
	private static final String SQL_INSERT		  		= "INSERT INTO Produit VALUES (?,?,?,?,?,?)";
	private static final String SQL_UPDATE_MINUS		= "UPDATE Produit SET QteStockP=QteStockP-? WHERE Ref_PRD=?";
	private static final String SQL_UPDATE_PLUS			= "UPDATE Produit SET QteStockP=QteStockP+? WHERE Ref_PRD=?";
	
	private DAOAccessoire daoAccessoire;
	private DAOOption daoOption;
	private DAOFactory daoFactory;
	
	public ProduitDAOImpl( DAOFactory daoFactory ) {
        this.daoFactory = daoFactory;
        daoAccessoire = daoFactory.getAccessoireDAO();
        daoOption = daoFactory.getOptionDAO();
    }
	
	@Override
	public void addProduit(Produit prod) throws DAOException{
		Connection connexion = null;
        PreparedStatement preparedStatementP = null;
        ResultSet valeursAutoGenerees = null;
        
        try {
            connexion = daoFactory.getConnection();
            
        	//Récupération du dernier numéro
            String strNewRef;
        	String strLastRef = this.getLastRef();
        	if(strLastRef == null)
        		strNewRef = "PRD_000001";
        	else if(strLastRef.length() == 10){
        		//Incrementation de cette derniere reference
        		String num = (Integer.parseInt(strLastRef.substring(5)) + 1) + ""; 
        		
        		while(num.length() < 6)
        			num = "0" + num;
        		
        		strNewRef = "PRD_" + num;
        	}
        	else{
                throw new DAOException( "Échec de la récupération de la dernière référence." );
        	}
        	
        	prod.setRef(strNewRef);
        	
            //insertion
	        preparedStatementP = DAOUtilitaire.initialisationRequetePreparee( connexion, SQL_INSERT, true,
	        		prod.getRef(), prod.getDescription(), prod.get_nomP(), prod.getPuP(), 
	        		prod.get_qteQtock(), prod.getCategorieP().getRef() );
            int statut = preparedStatementP.executeUpdate();
            if ( statut == 0 ) {
                throw new DAOException( "Échec de la création du produit, aucune ligne ajoutée dans la table." );
            }
            
            if(prod.getLstAccessoireP() != null){
            	daoAccessoire.lierAccessoires(prod);
            }
            if(prod.getLstOptionP() != null){
            	daoOption.lierOption(prod);
            }
        } catch ( SQLException e ) {
            throw new DAOException( e );
        } finally {
        	 DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, preparedStatementP, connexion );
        }
	}

	@Override
	public void updProduit(String pRef, int pQteCMD, boolean pMinus) throws DAOException{
		Connection oConnexion = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet valeursAutoGenerees = null;

        try {
        	oConnexion = this.daoFactory.getConnection();
        	
        	//mise a jour de la ligne commander
        	if(pMinus)
	        	oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnexion, SQL_UPDATE_MINUS, true,
	        			pQteCMD, pRef);
        	else
            	oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnexion, SQL_UPDATE_PLUS, true,
            			pQteCMD, pRef);
        	
            if ( oPreparedStatement.executeUpdate() == 0 )
                throw new DAOException( "Échec de la mise a jour du produit, aucune ligne modifiée dans la table." );

        }
        catch ( SQLException e ) {
            throw new DAOException( e );
        }
        finally {
        	 DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, oPreparedStatement, oConnexion );
        }
	}
	
	@Override
	public Produit trouverProduit(String ref, boolean dispo) throws DAOException{
		Connection connexion = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        Produit prod = new Produit();
        try {
            /* Récupération d'une connexion depuis la Factory */
            connexion = daoFactory.getConnection();
           
            //si l'on souhaite que le produit soit disponible
            if(dispo)
            	preparedStatement =  DAOUtilitaire.initialisationRequetePreparee( connexion, SQL_SELECT_DISPO, false, ref );
            else
            	preparedStatement =  DAOUtilitaire.initialisationRequetePreparee( connexion, SQL_SELECT_BY_ID, false, ref );
            
            resultSet = preparedStatement.executeQuery();
            /* Parcours de la ligne de données retournée dans le ResultSet */
            if ( resultSet.next() ) {
            	prod.set_nomP( resultSet.getString("NomP") );
            	prod.set_qteQtock( resultSet.getInt("QteStockP") );
            	prod.setPuP(resultSet.getDouble("PuP"));
            	prod.setRef(ref);
            	prod.setDescription( resultSet.getString("Description_PRD"));
            	
            	// récupération de la catégorie avec la DAO
            	Categorie cat = daoFactory.getCategorieDAO().trouverCategorie(resultSet.getString("CAT_Ref"));
            	prod.setCategorieP(cat);
            	
        		// récupération des options avec la DAO
        		HashMap<String, Option> lesOptions = daoFactory.getOptionDAO().listerOption(ref);
        		prod.setLstOptionP(lesOptions);
        		
        		// récupération des accessoires avec la DAO
        		Map<String, Accessoire> lesAccessoires = daoFactory.getAccessoireDAO().listerAccessoire(ref);
        		prod.setLstAccessoireP(lesAccessoires);
            }
        } catch ( SQLException e ) {
            throw new DAOException( e );
        } finally {
            DAOUtilitaire.fermeturesSilencieuses( resultSet, preparedStatement, connexion );
        }
        
        return prod;
	}
	
	@Override
	public String getLastRef() throws SQLException, DAOException {
		Connection oConnexion = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet resultSet = null;
        
        String strRef = null;

        try {
        	oConnexion = daoFactory.getConnection();
        	
        	oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnexion, SQL_SELECT_LAST, false);
            resultSet = oPreparedStatement.executeQuery();
            
            if ( resultSet.next() )
            	strRef = resultSet.getString("Ref_PRD");
        }
        catch ( SQLException e ) {
            throw new DAOException(e);
        }
        finally {
            DAOUtilitaire.fermeturesSilencieuses( resultSet, oPreparedStatement, oConnexion );
        }

        return strRef;
    }
}
